home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / ptv1n5.arc / L4.ASM < prev    next >
Assembly Source File  |  1990-11-07  |  4KB  |  93 lines

  1. ; Heavily optimized assembly language version of FindIDAverage.
  2. ; Features an unrolled loop and more efficient pointer use.
  3.  
  4. SearchedForID   equ     4       ;passed parameter offsets in the
  5. BlockPointer    equ     6       ; stack frame (skip over pushed BP
  6.                                 ; and the return address)
  7. NextBlock       equ     0       ;field offsets in struct BlockHeader
  8. BlockCount      equ     2
  9. BLOCK_HEADER_SIZE equ   4       ;# of bytes in struct BlockHeader
  10. ID              equ     0       ;struct DataElement field offsets
  11. Value           equ     2
  12. DATA_ELEMENT_SIZE equ   4       ;# of bytes in struct DataElement
  13.  
  14.         .model  small   
  15.         .code
  16.         public  _FindIDAverage
  17. _FindIDAverage  proc    near
  18.         push    bp              ;save caller's stack frame
  19.         mov     bp,sp           ;point to our stack frame
  20.         push    di              ;preserve C register variables
  21.         push    si
  22.         mov     di,ds           ;prepare for SCASW
  23.         mov     es,di
  24.         cld
  25.         sub     dx,dx           ;IDMatchSum = 0
  26.         mov     bx,dx           ;IDMatchCount = 0
  27.         mov     si,[bp+BlockPointer]    ;pointer to first block
  28.         mov     ax,[bp+SearchedForID]   ;ID we're looking for
  29. ; Search through all of the linked blocks until the last block
  30. ; (marked with a NULL pointer to the next block) has been searched.
  31. BlockLoop:
  32. ; Point to the first DataElement entry within this block.
  33.         lea     di,[si+BLOCK_HEADER_SIZE]
  34. ; Search through all the DataElement entries within this block
  35. ; and accumulate data from all that match the desired ID.
  36.         mov     cx,[si+BlockCount] ;# of elements in this block
  37.         jcxz    DoNextBlock     ;skip this block if it's empty
  38.         mov     bp,cx           ;***stack frame no longer available***
  39.         add     cx,7
  40.         shr     cx,1            ;# of repetitions of the unrolled
  41.         shr     cx,1            ; loop = (BlockCount + 7) / 8
  42.         shr     cx,1
  43.         and     bp,7            ;generate the entry point for the
  44.         shl     bp,1            ; first, possibly partial pass through
  45.         jmp     cs:[LoopEntryTable+bp] ; the unrolled loop and
  46.                                 ; vector to that entry point
  47.         align   2
  48. LoopEntryTable  label   word
  49.         dw      LoopEntry8,LoopEntry1,LoopEntry2,LoopEntry3
  50.         dw      LoopEntry4,LoopEntry5,LoopEntry6,LoopEntry7
  51.  
  52. M_IBL   macro   P1
  53.         local   NoMatch
  54. LoopEntry&P1&:
  55.         scasw                   ;do we have an ID match?
  56.         jnz     NoMatch         ;no match
  57.                                 ;we have a match
  58.         inc     bx              ;IDMatchCount++;
  59.         add     dx,[di]         ;IDMatchSum += DataPointer->Value;
  60. NoMatch:
  61.         add     di,DATA_ELEMENT_SIZE-2 ;point to the next element
  62.                                 ; (SCASW advanced 2 bytes already)
  63.         endm
  64.  
  65.         align   2
  66. IntraBlockLoop:
  67.         M_IBL   8
  68.         M_IBL   7
  69.         M_IBL   6
  70.         M_IBL   5
  71.         M_IBL   4
  72.         M_IBL   3
  73.         M_IBL   2
  74.         M_IBL   1
  75.         loop    IntraBlockLoop
  76. ; Point to the next block and continue if that pointer isn't NULL.
  77. DoNextBlock:
  78.         mov     si,[si+NextBlock] ;get pointer to the next block
  79.         and     si,si           ;is it a NULL pointer?
  80.         jnz     BlockLoop       ;no, continue
  81. ; Calculate the average of all matches.
  82.         sub     ax,ax           ;assume we found no matches
  83.         and     bx,bx
  84.         jz      Done            ;we didn't find any matches, return 0
  85.         xchg    ax,dx           ;prepare for division
  86.         div     bx              ;return IDMatchSum / IDMatchCount
  87. Done:   pop     si              ;restore C register variables
  88.         pop     di
  89.         pop     bp              ;restore caller's stack frame
  90.         ret     
  91. _FindIDAverage  ENDP
  92.         end
  93.